home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue60 / Focus / CtlFocus.pas < prev   
Encoding:
Pascal/Delphi Source File  |  2000-06-15  |  7.7 KB  |  280 lines

  1. {+--------------------------------------------------------------------------+
  2.  | Component:   TCtlFocus
  3.  | Created:     2000/06/15
  4.  | Author:      Hart Kerbel
  5.  | Company:     HartWare
  6.  | Copyright    2000, all rights reserved.
  7.  | Description: Control Focus.
  8.  | Version:            1.0
  9.  | Modification History:
  10.  +--------------------------------------------------------------------------+}
  11. unit CtlFocus;
  12.  
  13. interface
  14.  
  15. uses
  16.     Messages, Classes, Graphics, Controls, Forms;
  17.  
  18. const
  19.     DEFAULT_FOCUSED_COLOR = clYellow;
  20.  
  21. type
  22.     TNotifyColorChangeEvent = procedure (Sender: TObject; const AComponent : TComponent;
  23.                                                                              var ANewColor : TColor;
  24.                                                                              var AChangeColor : Boolean ) of object;
  25.  
  26. type
  27.     TCtlFocus = class(TComponent)
  28.     private
  29.         FHostForm : TCustomForm;                            // Refrence to form containing control.
  30.         FLastFocusedCtrl : TWinControl;                // Last control to be focused.
  31.  
  32.         FHostFormWndProc : TWndMethod;                // Host form's WndProc.
  33.  
  34.         FEnabled: Boolean;
  35.  
  36.         FFocusedColor: TColor;
  37.         FLastColor : TColor;                  // Remember the original color.
  38.  
  39.         {- Events Handlers. -}
  40.         FOnAfterFocus: TNotifyColorChangeEvent;
  41.         FOnBeforeFocus: TNotifyColorChangeEvent;
  42.  
  43.     protected
  44.         procedure FocusChanged;
  45.         procedure AlterCtrlState; virtual;
  46.         procedure RestoreCtrlState; virtual;
  47.  
  48.         procedure SetEnabled(const Value: Boolean); virtual;
  49.         procedure SetFocusedColor(const Value: TColor); virtual;
  50.  
  51.         procedure CtlFocusWndProc(var Message: TMessage); virtual;
  52.  
  53.         procedure DoBeforeFocus(var AChangeColor: Boolean;
  54.                                                         var AFocusedColor: TColor); virtual;
  55.         procedure DoAfterFocus(var AChangeColor: Boolean;
  56.                                                      var AFocusedColor: TColor;
  57.                                                      const AComponent :TComponent ); virtual;
  58.  
  59.         function SetColorProperty(AComponent: TComponent;
  60.                                                             var ACurrentColor: TColor;
  61.                                                             const AFocusedColor: TColor) : Boolean; virtual;
  62.  
  63.         function RunTime: Boolean;            // Returns true if it's run-time (vs design time).
  64.  
  65.     public
  66.         constructor Create(AOwner : TComponent); override;
  67.         destructor Destroy; override;
  68.  
  69.     published
  70.         property Enabled : Boolean
  71.             read FEnabled
  72.             write SetEnabled
  73.             default True;
  74.  
  75.         property FocusedColor : TColor
  76.             read  FFocusedColor
  77.             write SetFocusedColor
  78.             default DEFAULT_FOCUSED_COLOR;
  79.  
  80.         property OnBeforeFocus : TNotifyColorChangeEvent
  81.             read FOnBeforeFocus
  82.             write FOnBeforeFocus;
  83.  
  84.         property OnAfterFocus : TNotifyColorChangeEvent
  85.             read FOnAfterFocus
  86.             write FOnAfterFocus;
  87.     end; { TCtlFocus }
  88.  
  89.     procedure Register;
  90.  
  91. {==============================================================================}
  92.  
  93. implementation
  94. uses
  95.     TypInfo;
  96.  
  97. destructor TCtlFocus.Destroy;
  98. begin
  99.     {-
  100.         Restore original WndProc. Technically only required if CtlFocus is dynamically
  101.         created and destroyed, but a good practice to always follow.
  102.     -}
  103.     if RunTime then
  104.         FHostForm.WindowProc := FHostFormWndProc;
  105.  
  106.     inherited Destroy;
  107. end; { Destroy }
  108.  
  109. {------------------------------------------------------------------------------}
  110.  
  111. constructor TCtlFocus.Create(AOwner : TComponent);
  112. begin
  113.     inherited Create(AOwner);
  114.  
  115.     FHostForm := TCustomForm(AOwner);
  116.     FLastFocusedCtrl := nil;
  117.     FFocusedColor := DEFAULT_FOCUSED_COLOR;
  118.     Enabled := True;
  119.  
  120.     {- Subclass the host form if it is run time. -}
  121.     if RunTime then
  122.     begin
  123.         FHostFormWndProc := FHostForm.WindowProc;
  124.         FHostForm.WindowProc := CtlFocusWndProc;
  125.     end;
  126. end; { Create }
  127.  
  128. {------------------------------------------------------------------------------}
  129.  
  130. procedure TCtlFocus.SetEnabled(const Value: Boolean);
  131. begin
  132.     FEnabled := Value;
  133.  
  134.     if FEnabled then
  135.         FocusChanged
  136.     else
  137.         RestoreCtrlState;
  138. end; { SetEnabled }
  139.  
  140. {------------------------------------------------------------------------------}
  141.  
  142. procedure TCtlFocus.SetFocusedColor(const Value: TColor);
  143. begin
  144.     FFocusedColor := Value;
  145.  
  146.     if Enabled then
  147.         FocusChanged;
  148. end; { SetFocusedColor }
  149.  
  150. {------------------------------------------------------------------------------}
  151.  
  152. procedure TCtlFocus.CtlFocusWndProc(var Message: TMessage);
  153. begin
  154.     case Message.Msg of
  155.         CM_FOCUSCHANGED:      // Focus has shifted within form.
  156.             FocusChanged;
  157.  
  158.         CM_DEACTIVATE:                // Host form is about to loose focus.
  159.             RestoreCtrlState;
  160.  
  161.         CM_ACTIVATE:                    // Host form is about to (re)gain focus.
  162.             FocusChanged;
  163.     end; {case}
  164.  
  165.     {- Pass all messages on to original WndProc. -}
  166.     FHostFormWndProc(Message);
  167. end; { CtlFocusWndProc }
  168.  
  169. {------------------------------------------------------------------------------}
  170.  
  171. procedure TCtlFocus.FocusChanged;
  172. begin
  173.     if not Enabled then
  174.         Exit;
  175.  
  176.     RestoreCtrlState;
  177.     AlterCtrlState;
  178. end; { FocusChanged }
  179.  
  180. {------------------------------------------------------------------------------}
  181.  
  182. {- Trigger OnBeforeFocus event then change the color property. -}
  183. procedure TCtlFocus.AlterCtrlState;
  184. var
  185.     bChangeColor : Boolean;
  186.     clFocusedColor : TColor;
  187. begin
  188.     clFocusedColor := FFocusedColor;    // Set default color.
  189.     bChangeColor := True;                             // Default action is to change the color.
  190.  
  191.     DoBeforeFocus(bChangeColor, clFocusedColor);    // Opportunity to override default settings.
  192.  
  193.     if bChangeColor then
  194.         SetColorProperty(FHostForm.ActiveControl, FLastColor, clFocusedColor);
  195.  
  196.     FLastFocusedCtrl := FHostForm.ActiveControl;
  197. end; { AlterCtrlState }
  198.  
  199. {------------------------------------------------------------------------------}
  200.  
  201. {- Trigger the OnAfterFocus event then resore the color. -}
  202. procedure TCtlFocus.RestoreCtrlState;
  203. var
  204.     bChangeColor : Boolean;
  205.     sink : TColor;
  206. begin
  207.     if FLastFocusedCtrl <> nil then
  208.     begin
  209.         bChangeColor := True;         // The default action is to change the color.
  210.         DoAfterFocus(bChangeColor, FLastColor, FLastFocusedCtrl);
  211.  
  212.         if bChangeColor then
  213.             SetColorProperty(FLastFocusedCtrl, sink, FLastColor);
  214.     end;
  215. end; { RestoreCtrlState }
  216.  
  217. {------------------------------------------------------------------------------}
  218.  
  219. {- Trigger the OnAfterFocus event just before the control looses focus. -}
  220. procedure TCtlFocus.DoAfterFocus(var AChangeColor: Boolean; var AFocusedColor: TColor; const AComponent: TComponent);
  221. begin
  222.     if Assigned(FOnAfterFocus) then
  223.         FOnAfterFocus(Self, AComponent, AFocusedColor, AChangeColor);
  224. end; { DoAfterFocus }
  225.  
  226. {------------------------------------------------------------------------------}
  227.  
  228. {- Trigger the OnBeforeFocus event just before the control receives focus. -}
  229. procedure TCtlFocus.DoBeforeFocus(var AChangeColor: Boolean; var AFocusedColor : TColor);
  230. begin
  231.     if not Assigned(FHostForm.ActiveControl) then
  232.         Exit;                                                                    // No active control.
  233.  
  234.     if Assigned(FOnBeforeFocus) then
  235.         FOnBeforeFocus(Self, FHostForm.ActiveControl, AFocusedColor, AChangeColor);
  236. end; { DoBeforeFocus }
  237.  
  238. {------------------------------------------------------------------------------}
  239.  
  240. {- Set the color property of AComponent using RTTI. -}
  241. function TCtlFocus.SetColorProperty(AComponent: TComponent;
  242.     var ACurrentColor: TColor; const AFocusedColor: TColor): Boolean;
  243. var
  244.     PropInfo : PPropInfo;
  245. begin
  246.     if not Assigned(AComponent) then
  247.     begin
  248.         Result := False;
  249.         Exit;
  250.     end;
  251.  
  252.     PropInfo := GetPropInfo(AComponent.ClassInfo, 'Color', [tkInteger]);
  253.     if PropInfo = nil then
  254.     begin
  255.         Result := False;
  256.         Exit;
  257.     end;
  258.  
  259.     Result := True;
  260.  
  261.     ACurrentColor := TColor(GetOrdProp(AComponent, PropInfo));
  262.  
  263.     SetOrdProp(AComponent, PropInfo, LongInt(AFocusedColor));
  264. end; { SetColorProperty }
  265.  
  266. {------------------------------------------------------------------------------}
  267.  
  268. function TCtlFocus.RunTime: Boolean;
  269. begin
  270.     RunTime := not (csDesigning in ComponentState);
  271. end; { RunTime }
  272.  
  273.  
  274. procedure Register;
  275. begin
  276.     RegisterComponents('DDJ', [TCtlFocus]);
  277. end; { Register }
  278.  
  279. end.
  280.